package client.game;

import client.Client;
import java.nio.ByteBuffer;
import shared.client.io.ClientCommand;
import shared.net.protocol.ServerHeader;
import shared.util.PacketIO;
import shared.util.Pair;

/**
 * This class stores game information. Also, control transfers here
 * (from the main User IO loop) when a game begins.
 *
 * @author Vincent Tsuei
 * @version 2012-11-28
 */
public class Game {

    private Client client;
    private long ID;
    private String opponent;
    private int[] sets;
    private boolean clientsTurn;
    private boolean over = false;

    public Game(long id, String op, int[] pileCounts, Client c, boolean b) {
        this.client = c;
        this.ID = id;
        this.opponent = op;
        this.sets = pileCounts;
        this.clientsTurn = b;
    }

    /**
     * This loop runs when the player is in a game.
     */
    public void run() throws InterruptedException {
        while (!over) {
            if (clientsTurn) {
                client.getUserIO().write("It is your turn.", true);
                Pair<ClientCommand, String[]> command = null;
                boolean valid = false;
                while (!valid) {
                    command = client.getUserIO().PromptMenu(false);
                    valid = true;
                }
                client.getCommandHandler().handleCommand(command.getLeft(), command.getRight());
            } else {
                client.getUserIO().write("It is the opponent's turn. Please wait.", true);
                client.waitForPacket(this, ServerHeader.Send.GAME_UPDATE);
                
                ByteBuffer b = client.retrieveWaitResponse();
                byte resp = b.get();
                
                //We can only get a positive response here.
                if (resp == 1) {
                    String msg = PacketIO.readString(b);
                    client.getUserIO().write(msg, true);
                    long gameID = b.getLong();
                    clientsTurn = (b.get() == 1);
                    int[] piles = new int[b.getInt()];
                    for (int i = 0; i < piles.length; i++) {
                        piles[i] = b.getInt();
                    }
                    sets = piles;
                } else {
                    throw new RuntimeException("Unhandled packet structure.");
                }
            }
        }
    }

    /**
     * Get a user friendly game state string.
     */
    public String getGameStateString() {
        StringBuilder sb = new StringBuilder();
        sb.append("Opponent: ").append(opponent);
        sb.append(" | ");
        for (int i : sets) {
            sb.append(i);
            sb.append(" ");
        }
        return sb.toString();
    }

    /**
     * Update the game with new set counts. 
     * Also, specify if it is now the client's turn.
     */
    public void updateGame(int[] i, boolean clientsT) {
        this.sets = i;
        this.clientsTurn = clientsT;
        checkGameOver();
    }
    
    /**
     * Check that the game is over (i.e. all the sets are 0).
     */
    private void checkGameOver() {
        for (int i : sets) {
            if (i > 0) {
                return;
            }
        }
        setOver();
    }
    
    /**
     * Set that the game is over. This may occur naturally, or
     * because the other player disconnected.
     */
    public void setOver() {
        over = true;
    }
    
    /**
     * Return whether the game is over.
     */
    public boolean isGameOver() {
        return over;
    }
}
